package org.jackysoft.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.jackysoft.entity.AcegiRole;
import org.jackysoft.entity.TreeNode;
import org.jackysoft.entity.User;
import org.jackysoft.google.collection.TreeNodeZtreeFunction;
import org.jackysoft.google.collection.ZTreeNode;
import org.jackysoft.opensymphony.workflow.TreeNodeDeleteWork;
import org.jackysoft.service.AbstractIdentifiedService;
import org.jackysoft.service.TreeNodeService;
import org.jackysoft.util.SpringSecurityUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

@Service
@Transactional
public class TreeNodeServiceImpl 
extends AbstractIdentifiedService<TreeNode>
implements TreeNodeService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7568888199425706132L;

	public TreeNodeServiceImpl() {
		this.type = TreeNode.class;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Collection<TreeNode> getsSimpled() {
		String hql = "select new TreeNode(a.id,a.description) from TreeNode a where a.type='folder' and a.parentId='root' and a.visiable=true";
		Session session = getSession();
		return session.createQuery(hql).list();
	}

	
	@Override
	@SuppressWarnings("unchecked")
	public Collection<TreeNode> getsByParentAndCurrentUser(String parentId) {
		User cu = SpringSecurityUtils.getCurrentUser();
		Collection<AcegiRole> auths = null;
		Session session = getSession();
		auths = cu.getAuthoritys();
		List<TreeNode> alist;
		if (auths != null && auths.size() != 0) {
			String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
					+ "from TreeNode a join a.permissions pms where a.parentId=:parentId  and pms in (:perm) and a.visiable=true";
			alist = session.createQuery(hql).setParameterList("perm", auths)
					.setString("parentId", (String) parentId).list();
		} else {
			String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
					+ "from TreeNode a where a.parentId=:parentId and a.visiable=true";
			alist = session.createQuery(hql)
					.setString("parentId", (String) parentId).list();
		}
		Collections.sort(alist);
		return alist;

	}

	/**
	 * 返回所有资源,用于权限分配
	 * */
	@Override
	public Collection<TreeNode> getsByParent(String parentId)
			throws DataAccessException {
		Session session = getSession();
		List<TreeNode> alist = new ArrayList<TreeNode>();
		String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort,a.visiable,a.webapp,a.catalog) "
				+ "from TreeNode a  where a.parentId=:parentId";
		alist = session.createQuery(hql)
				.setString("parentId", (String) parentId).list();
		Collections.sort(alist);
		return alist;
	}

	/**
	 * 获得当前用户权限所分配的树节点
	 * 
	 * @param parentId
	 *            父ID
	 * @param acegi
	 *            角色编号
	 * @param htpsession
	 *            HttpSession
	 * @return Collection<TreeNode> 符合树节点集合
	 * */
	@Override
	public Collection<TreeNode> getsByParentAndSecurole(String parentId,
			String acegi) throws DataAccessException {
		List<TreeNode> alist = new ArrayList<TreeNode>();
		Session session = getSession();
		Collection<AcegiRole> auths = new ArrayList<AcegiRole>();
		AcegiRole a = new AcegiRole();
		a.setName(acegi);
		auths.add(a);
		String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
				+ "from TreeNode a join a.permissions pms where a.parentId=:parentId  and pms in (:perm)";
		alist = session.createQuery(hql).setParameterList("perm", auths)
				.setString("parentId", (String) parentId).list();
		return alist;
	}

	@Override
	public Collection<TreeNode> getsCheckboxedByParent(String parentId)
			throws DataAccessException {
		UserDetails u = SpringSecurityUtils.getCurrentUser();
		Collection<AcegiRole> auths = null;
		Session session = getSession();
		User cu = (User) session.get(User.class, u.getUsername());
		auths = cu.getAuthoritys();
		List<TreeNode> alist = new ArrayList<TreeNode>();
		if (auths != null && auths.size() != 0) {
			String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
					+ "from TreeNode a join a.permissions pms where a.parentId=:parentId  and pms in (:perm) and a.visiable=true";
			alist = session.createQuery(hql).setParameterList("perm", auths)
					.setString("parentId", (String) parentId).list();
		}
		Collections.sort(alist);
		return alist;
	}

	@Override
	public void create(TreeNode t) throws DataAccessException {
		t.setId(null);
		super.create(t);
	}

	
	@Override
	public void remove(TreeNode t) throws DataAccessException {
		Session sess = getSession();
		sess.doWork(new TreeNodeDeleteWork(t.getId()));
		sess.clear();
		
	}
		
	@Override
	public void update(TreeNode t) throws DataAccessException {
		Session sess = getSession();
		String hql = "update TreeNode t set t.webapp=:webapp, t.identifier=:identifier,t.description=:description,t.visiable=:visiable,t.type=:type,t.catalog=:catalog where t.id=:id";
		sess.createQuery(hql).setString("identifier", t.getIdentifier())
				.setString("description", t.getDescription())
				.setBoolean("visiable", t.isVisiable())
				.setParameter("webapp", t.getWebapp())
				.setParameter("catalog", t.getCatalog())
				.setString("type", t.getType())
				.setString("id", t.getId())
				.executeUpdate();

	}

	@Override
	public void batchUpdateSorted(Collection<TreeNode> trees)
			throws DataAccessException {
		assert trees != null : "参数错误";
		Session sess = getSession();
		String hql = "update TreeNode t set t.sort=:sort where t.id=:id";
		int count = 0;
		for (TreeNode t : trees) {
			Query update = sess.createQuery(hql);
			update.setInteger("sort", t.getSort())
					.setString("id", t.getId()).executeUpdate();
			if (++count % 10 == 0) {
				sess.flush();
				sess.clear();
			}

		}

	}

	

	@Override
	public Collection<TreeNode> getsByCurrentUser(String parentId)
			throws DataAccessException {
		User user = SpringSecurityUtils.getCurrentUser();
		Collection<AcegiRole> auths = user.getAuthoritys();
		Collection<AcegiRole> applys = Lists.newArrayList();
		for(AcegiRole r : auths){
			if(r.isEnabled()) applys.add(r);
		}
		return getTreeNodes(parentId, applys);
	}

	private Collection<TreeNode> getTreeNodes(String parentId,Collection<AcegiRole> auths) {
		Session session = getSession();
		List<TreeNode> alist;
		
		String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort,a.webapp,a.catalog) "
				+ "from TreeNode a join a.permissions pms where a.parentId=:parentId  and pms in (:perm) and a.visiable=true order by a.sort";
		alist = session.createQuery(hql).setParameterList("perm", auths)
				.setString("parentId", (String) parentId).list();
		
		return alist;
	}

	@Override
	public Collection<TreeNode> getsByCurrentUser()
			throws DataAccessException {
		Session session = getSession();
		User user = SpringSecurityUtils.getCurrentUser();
		Collection<AcegiRole> auths = user.getAuthoritys();
		List<TreeNode> alist;
		String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
				+ "from TreeNode a join a.permissions pms where  pms in (:perm)";
		alist = session.createQuery(hql).setParameterList("perm", auths).list();
		return alist;
	}

	/**
	 * 取得某个权限的所有资源编号
	 * */
	@Override
	public Collection<TreeNode> getsBySecurole(AcegiRole secRole)
			throws DataAccessException {
		Session session = getSession();
		Collection<AcegiRole> auths = Sets.newHashSet();
		auths.add(secRole);
		String hql = "select distinct new TreeNode(a.id,a.identifier,a.description,a.leaf,a.parentId,a.type,a.sort) "
				+ "from TreeNode a join a.permissions pms where  pms in (:perm) ";
		List<TreeNode> alist = session.createQuery(hql)
				.setParameterList("perm", auths).list();
		return alist;
	}

	@Override
	public Collection<ZTreeNode> ztree(TreeNode bean)
			throws DataAccessException {
		if(bean==null){
			bean= new TreeNode();
			bean.setId("root");
		}
		Collection<TreeNode> trees = getsByCurrentUser(bean.getId());
		return Collections2.transform(trees,new TreeNodeZtreeFunction());
	}
	
	
	

}